/*
Copyright 2010 Bryce Alcock

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.com

 */
package com.ecocrypt.proxy.forwarder;

import com.ecocrypt.proxy.forwarder.remote.ForwarderDynamicStateChangedPayload;
import com.ecocrypt.proxy.forwarder.transfer.ForwarderListener;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;

/**
 *
 * @author Bryce.Alcock
 */
public class RemoteForwarderStub extends Forwarder implements Serializable {


    private final HashMap< Integer,ClientServiceRequest> requests = new HashMap< Integer,ClientServiceRequest>();

    {
        listenerList = new ArrayList<ForwarderListener>();
    }
    
    public RemoteForwarderStub(String forwardDefinition) {
        super(forwardDefinition, true);
    }

    private ForwarderDynamicStateChangedPayload dynamicState;

    /**
     * @param dynamicState the dynamicState to set
     */
    public void setDynamicState(ForwarderDynamicStateChangedPayload dynamicState) {
        this.dynamicState = dynamicState;
        currentRequestId = dynamicState.currentRequestId;//new AtomicInteger(-1);
        errorCount = dynamicState.errorCount;//new AtomicInteger(-1);
        activeCount = dynamicState.activeCount;//new AtomicInteger(-1);
        totalBytesToEngine = dynamicState.totalBytesToEngine;//new AtomicLong(-1);
        totalBytesFromEngine = dynamicState.totalBytesFromEngine;//new AtomicLong(-1);
        totalBytesToClient = dynamicState.totalBytesToClient;//new AtomicLong(-1);
        totalBytesFromClient = dynamicState.totalBytesFromClient;//new AtomicLong(-1);
        
        broadcastCurrentStatus();
    }

       //@StateChange
    private void broadcastCurrentStatus() {
        System.out.println("Broadcasting status changed: " + this.toString());
        for (ForwarderListener forwarderListener : listenerList) {
            System.out.println("Broadcasting status changed: FowarderListener " + this.toString());
            forwarderListener.forwarderDynamicStateChanged(this);
        }
	printOut();
    }

    private void printOut(){
	StringBuilder sb = new StringBuilder("RemoteForwarderStub : ");
	sb.append("\n\tcurrentRequestId").append(currentRequestId);
	sb.append("\n\terrorCount").append(errorCount);
	sb.append("\n\tactiveCount").append(activeCount);
	sb.append("\n\ttotalBytesToEngine").append(totalBytesToEngine);
	sb.append("\n\ttotalBytesFromEngine").append(totalBytesFromEngine);
	sb.append("\n\ttotalBytesToClient").append(totalBytesToClient);
	sb.append("\n\ttotalBytesFromClient").append(totalBytesFromClient);
	System.out.println(sb.toString());
    }
    public String forwarderName;
    /*
     * NOT NEEDED BECAUSE THE TRANSIENT PARENT CLASS FIELDS WILL GET POPULATED.
     * public AtomicInteger currentRequestId = new AtomicInteger(-1);
     * public AtomicInteger errorCount = new AtomicInteger(-1);
     * public AtomicInteger activeCount = new AtomicInteger(-1);
     * public AtomicLong totalBytesToEngine = new AtomicLong(-1);
     * public AtomicLong totalBytesFromEngine = new AtomicLong(-1);
     * public AtomicLong totalBytesToClient = new AtomicLong(-1);
     * public AtomicLong totalBytesFromClient = new AtomicLong(-1);
     */

    @Override
    public ArrayList<ClientServiceRequest> getCurrentRequests() {
        ArrayList<ClientServiceRequest> reqs = new ArrayList<ClientServiceRequest>();

        synchronized (requests) {
            for (ClientServiceRequest clientServiceRequest : requests.values()) {
                reqs.add(clientServiceRequest);
            }
        }
        return reqs;
    }
    public void addServiceRequest(ClientServiceRequest csr){
	requests.put(csr.serviceId,csr);
        for (ForwarderListener forwarderListener : listenerList) {
             forwarderListener.connectionAdded(this);
         }
    }

    @Override
    public void connectionDataChanged(ClientServiceRequest csr) {

	System.out.println("888888888888888888888888***********************\n"+csr.toString());
	if(requests.get(csr.serviceId)!=null){
	System.out.println("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n");
	    requests.put(csr.serviceId,csr);
            for (ForwarderListener forwarderListener : listenerList) {
                forwarderListener.connectionDataChanged(this, csr);
            }
	}else{
	System.out.println("-----------------------------------------------------------\n");

	}
    }



    // Remove Finished Service Requests.
    @Override
    public void removeServiceRequest(ClientServiceRequest csr) {
	// TODO this is not close to finished.
	// There is alot of logic that has too be hammered out:
	//  1.  new Service Requests.
	//  2.  Synchronizing state.
	//  3.  boundary checking and efficiency.
        synchronized (requests) {
            ClientServiceRequest ret = requests.remove(csr.serviceId);
            if (ret != null) {
                activeCount.decrementAndGet();
                for (ForwarderListener forwarderListener : listenerList) {
                    forwarderListener.connectionRemoved(this, csr);
                }
            }else{
		// We are removing a reqeust before it was created, This is
		// posible in the remoteForwarderStub because.
		//   ................................
		//  We will have to add it to a list of requests.
		//  If the list gets too large, we will have to request
		//  a re-sync.
                for (ForwarderListener forwarderListener : listenerList) {
                    forwarderListener.connectionRemoved(this, csr);
                }
	    }
        }
    }
}
